using System;
using System.Text;

namespace BarcodeDecoder
{
    /// <summary>
    /// 条码解析器 - 从二进制条码字符串解析项目号和批次
    /// </summary>
    public static class BarcodeDecoder
    {
        /// <summary>
        /// 从条码字符串解析项目号和批次
        /// </summary>
        /// <param name="barcodeString">二进制条码字符串（只包含0和1）</param>
        /// <returns>包含项目号和批次的元组，解析失败返回null</returns>
        public static (int ProjectId, int BatchId)? DecodeBarcode(string barcodeString)
        {
            if (string.IsNullOrEmpty(barcodeString))
                return null;

            // 验证输入只包含0和1
            foreach (char c in barcodeString)
            {
                if (c != '0' && c != '1')
                    return null;
            }

            try
            {
                // 步骤1：解析为编码字符串
                string encodedString = DecodeBarcodeToEncoded(barcodeString);
                if (encodedString == null)
                    return null;

                // 步骤2：解析为15位二进制
                string binaryString = DecodeEncodedToBinary(encodedString);
                if (binaryString == null)
                    return null;

                // 步骤3：转换为数字
                int number = BinaryToNumber(binaryString);
                if (number == -1)
                    return null;

                // 步骤4：验证数字是否满足条件
                if (!Verify15BitCondition(number))
                    return null;

                // 步骤5：查找条码编号
                int barcodeNumber = FindBarcodeNumberBy15Bit(number);
                if (barcodeNumber == -1)
                    return null;

                // 步骤6：计算项目编号和批次
                return BarcodeNumberToProjectBatch(barcodeNumber);
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 将条码字符串解析为编码字符串
        /// 规则：11→A, 00→B, 1→C, 0→D
        /// </summary>
        private static string DecodeBarcodeToEncoded(string barcodeString)
        {
            if (string.IsNullOrEmpty(barcodeString))
                return null;

            StringBuilder encoded = new StringBuilder();
            int i = 0;

            while (i < barcodeString.Length)
            {
                if (i + 1 < barcodeString.Length)
                {
                    // 检查两位模式
                    string twoBits = barcodeString.Substring(i, 2);
                    if (twoBits == "11")
                    {
                        encoded.Append('A');
                        i += 2;
                        continue;
                    }
                    else if (twoBits == "00")
                    {
                        encoded.Append('B');
                        i += 2;
                        continue;
                    }
                }

                // 单位模式
                if (barcodeString[i] == '1')
                    encoded.Append('C');
                else
                    encoded.Append('D');
                i++;
            }

            return encoded.ToString();
        }

        /// <summary>
        /// 将编码字符串解析为15位二进制字符串
        /// 规则：偶数位置 A→1,C→0；奇数位置 B→1,D→0
        /// </summary>
        private static string DecodeEncodedToBinary(string encodedString)
        {
            if (string.IsNullOrEmpty(encodedString) || encodedString.Length != 15)
                return null;

            StringBuilder binary = new StringBuilder();

            for (int i = 0; i < encodedString.Length; i++)
            {
                char c = encodedString[i];
                if (i % 2 == 0) // 偶数位置
                {
                    if (c == 'A')
                        binary.Append('1');
                    else if (c == 'C')
                        binary.Append('0');
                    else
                        return null; // 偶数位置只能是A或C
                }
                else // 奇数位置
                {
                    if (c == 'B')
                        binary.Append('1');
                    else if (c == 'D')
                        binary.Append('0');
                    else
                        return null; // 奇数位置只能是B或D
                }
            }

            return binary.ToString();
        }

        /// <summary>
        /// 将15位二进制字符串转换为数字
        /// </summary>
        private static int BinaryToNumber(string binaryString)
        {
            if (string.IsNullOrEmpty(binaryString) || binaryString.Length != 15)
                return -1;

            try
            {
                return Convert.ToInt32(binaryString, 2);
            }
            catch
            {
                return -1;
            }
        }

        /// <summary>
        /// 验证15位数是否满足条件
        /// 条件：15位二进制数按3位一组分组，每组中1的个数之和等于6
        /// </summary>
        private static bool Verify15BitCondition(int number)
        {
            if (number < 0 || number >= 0x8000)
                return false;

            int group1Count = 0; // 位 0,3,6,9,12
            int group2Count = 0; // 位 1,4,7,10,13  
            int group3Count = 0; // 位 2,5,8,11,14

            int tempNum = number;
            for (int i = 0; i < 5; i++)
            {
                group1Count += tempNum & 1;
                tempNum >>= 1;
                group2Count += tempNum & 1;
                tempNum >>= 1;
                group3Count += tempNum & 1;
                tempNum >>= 1;
            }

            return (group1Count + group2Count + group3Count) == 6;
        }

        /// <summary>
        /// 根据15位数查找对应的条码编号
        /// </summary>
        private static int FindBarcodeNumberBy15Bit(int targetNumber)
        {
            if (targetNumber < 0 || targetNumber >= 0x8000)
                return -1;

            // 验证这个数字是否满足条件
            if (!Verify15BitCondition(targetNumber))
                return -1;

            // 查找这是第几个满足条件的数字
            int count = 0;
            for (int num = 0; num <= targetNumber; num++)
            {
                if (Verify15BitCondition(num))
                {
                    count++;
                    if (num == targetNumber)
                        return count;
                }
            }

            return -1;
        }

        /// <summary>
        /// 将条码编号转换为项目编号和批次
        /// 公式：条码编号 = (项目编号-1) * 60 + 批次
        /// </summary>
        private static (int ProjectId, int BatchId)? BarcodeNumberToProjectBatch(int barcodeNumber)
        {
            if (barcodeNumber < 1 || barcodeNumber > 4800) // 80*60 = 4800
                return null;

            // 反向计算
            // 条码编号 = (项目编号-1) * 60 + 批次
            // 所以：项目编号 = ((条码编号-1) / 60) + 1
            //      批次 = ((条码编号-1) % 60) + 1

            int projectId = ((barcodeNumber - 1) / 60) + 1;
            int batchId = ((barcodeNumber - 1) % 60) + 1;

            // 验证范围
            if (projectId >= 1 && projectId <= 80 && batchId >= 1 && batchId <= 60)
                return (projectId, batchId);

            return null;
        }
    }

    /// <summary>
    /// 示例程序
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            // 测试用例
            string[] testCases = {
                "110010011010101011001", // 项目80, 批次3
                "101010101001100110011", // 项目1, 批次1
                "101010101101100110011", // 项目1, 批次2
                "101010110010011011001", // 项目2, 批次1
                "101011010010010011001"  // 项目4, 批次60
            };

            Console.WriteLine("=== C# 条码解析器测试 ===\n");

            foreach (string barcode in testCases)
            {
                Console.WriteLine($"条码: {barcode}");
                
                var result = BarcodeDecoder.DecodeBarcode(barcode);
                
                if (result.HasValue)
                {
                    Console.WriteLine($"解析结果: 项目{result.Value.ProjectId}, 批次{result.Value.BatchId}");
                }
                else
                {
                    Console.WriteLine("解析失败");
                }
                
                Console.WriteLine();
            }

            // 交互式测试
            Console.WriteLine("输入条码字符串进行测试（输入 'exit' 退出）:");
            while (true)
            {
                Console.Write("请输入条码: ");
                string input = Console.ReadLine();
                
                if (string.IsNullOrEmpty(input) || input.ToLower() == "exit")
                    break;

                var result = BarcodeDecoder.DecodeBarcode(input);
                
                if (result.HasValue)
                {
                    Console.WriteLine($"✓ 项目编号: {result.Value.ProjectId}, 批次: {result.Value.BatchId}");
                }
                else
                {
                    Console.WriteLine("✗ 解析失败");
                }
                Console.WriteLine();
            }
        }
    }
}
